#coding=utf-8
import AutoLocate as AL             # 自动检测reg；
import os
import shutil
import cv2
import math
import colorCvt as CVT
import numpy as np
from DetailReserve import CalcSpatialImg, CalcDetailReserve, CalcLinearSpatialAndMtf
from ExcelManager import  *
#
#
#       对于第一种图像， 总共有8个reg要识别， 最左边的四个为枯叶图的四个， 后面的四个为24色卡的， 这里默认是识别正常的；
#
#

regNum = 8              # 8个reg;
imgDir = os.getcwd() + "/DxOMark-1+nord/"
imgExt = ".jpg"

LightImgs = {}              # 所有的图像；  键为光源， 键值为光源下拍摄的所有的图像；
FilterExpr = "Lux"          # 默认光源目录是有该标记的；

stdLab = [67.88, 0.45, -2.13]

# 枯叶图截取大小；
CROP_SIZE = 256
startDr = 20.0          # 用于细节保留拉伸；
endDr = 58.0

# 对色卡的区域进行划分， 取对应的块；
widthSplit = 8                  # 列划分；
heightSplit = 6                 # 行划分；
pickRatio2 = 4.2                   # 取第四个；
pickRatio1 = 4.5                 #

#   是否定位成功一张作为其他的；
bSame = False

def CalcDistance(pt1, pt2):
    """
    计算两点的距离；
    :param pt1:
    :param pt2:
    :return:
    """
    sum = 0
    sum = math.sqrt(math.pow(pt1[0] - pt2[0], 2.0) + math.pow(pt1[1] - pt2[1], 2.0))
    return sum

def LocateDeadLeaveAnd24ColorChart(regCenters):
    """
    枯叶图\24色卡定位；
    :return:
    """
    deadLeaveRegs = []
    colorChartRegs = []
    if len(regCenters) != 8:
        print("定位点数不对")
        return deadLeaveRegs,colorChartRegs
    xVec = []
    for c in regCenters:
        xVec.append(c[1])
    b = sorted(enumerate(xVec), key=lambda x: x[1])

    for idx in b[0:4]:
        deadLeaveRegs.append(regCenters[idx[0]])

    for idx in b[4:8]:
        colorChartRegs.append(regCenters[idx[0]])
    return deadLeaveRegs, colorChartRegs

def CalcRegCenter(contour):
    """
    计算所有的reg的中心；
    :param contours:
    :return:
    """
    center = [0] * 2
    nContour = len(contour)
    if nContour == 0:
        return center
    num = 0
    for c in range(nContour):
        x, y = contour[c][0]            # y为行， x为列；
        center[0] = center[0] + y
        center[1] = center[1] + x
        num = num + 1
    center[0] = 1.0 * center[0]/num
    center[1] = 1.0 * center[1]/num
    return center

def WalkAllLightsDir(path):
    """
    先搜索找到所有的图像；
    :param path:
    :return:
    """
    if not os.path.exists(path):
        print("该路径不存在！")
        return False
    # 遍历所有的光源目录， 找到所有的图像；
    LightImgs.clear()
    for root, dirs, files in os.walk(path):
        for dir in dirs:
            if dir.find(FilterExpr) != -1:
                print(os.path.join(root, dir))
                for r, d, f in os.walk(os.path.join(root, dir)):
                    newFs = []
                    for t in f:
                        if t[-3:] == "jpg":
                            newFs.append(t)
                    LightImgs[dir] = newFs

def CropDeadLeave(regs):
    """
    裁剪出枯叶图；
    :param regs:
    :return:
    """
    if len(regs) != 4:
        print("reg数不对")
        return
    # 直接算中心；
    center = [0] * 2
    for r in regs:
        center[0] = center[0] + r[0]
        center[1] = center[1] + r[1]
    center[0] = center[0]/len(regs)
    center[1] = center[1]/len(regs)

    DeadleaveHeight = CalcDistance(regs[0], regs[1])

    # CropHeight = 0.6 * DeadleaveHeight          # 裁剪高度；
    # CropWidth = CropHeight

    # 固定裁剪大小；
    CropHeight = CROP_SIZE  # 裁剪高度；
    CropWidth = CROP_SIZE

    CropRect = [center[0] - CropHeight/2, center[1] - CropWidth/2, CropWidth, CropHeight]           # 左上角 行， 列， 宽， 高；
    return CropRect

def Crop24ColorChart(regs):
    """
    裁剪24色卡；
    :param regs:
    :return:
    """
    if len(regs) != 4:
        print("reg数不对")
        return
    # 排序；
    LeftTop, RightTop, LeftBtm, RightBtm = [None] * 4
    if regs[0][0] > regs[1][0]:    # 行比较；
        LeftTop = regs[1]
        LeftBtm = regs[0]
    else:
        LeftTop = regs[0]
        LeftBtm = regs[1]
    if regs[2][0] > regs[3][0]:
        RightTop = regs[3]
        RightBtm = regs[2]
    else:
        RightTop = regs[2]
        RightBtm = regs[3]
    AreaHeight = CalcDistance(LeftTop, LeftBtm)
    AreaWidth = CalcDistance(LeftTop, RightTop)
    blockWidth = AreaWidth/widthSplit
    blockHeight = AreaHeight/heightSplit
    pickRect = [0] * 4
    pickRect[2] = blockWidth * 0.5
    pickRect[3] = blockHeight * 0.5
    pickRect[0] = LeftTop[0] + pickRatio1 * blockHeight
    pickRect[1] = LeftTop[1] + pickRatio2 * blockWidth
    return pickRect

def SortFourCornor(cornors):
    """
    无规律排列
    :param cornors:
    :return:
    """
    sumMax = -1e10
    sumMin = 1e10
    subMax = sumMax
    subMin = sumMin
    LeftTop, RightTop, Leftbtm, RightBtm = [None] * 4
    for i in range(len(cornors)):
        tmpCornor = cornors[i]
        tmpDis = tmpCornor[0] + tmpCornor[1]
        if tmpDis > sumMax:
            sumMax = tmpDis
            RightBtm = tmpCornor
        if tmpDis < sumMin:
            sumMin = tmpDis
            LeftTop = tmpCornor
        tmpDis = tmpCornor[0] - tmpCornor[1]            # 列 - 行；
        if tmpDis > subMax:
            subMax = tmpDis
            RightTop = tmpCornor
        if tmpDis < subMin:
            subMin = tmpDis
            Leftbtm = tmpCornor
    return [LeftTop, RightTop, RightBtm, Leftbtm]           # 顺序；

def GetRoiCornor(regs):
    """
    从很多个regs中得到所要的8个顶点；
    :param regCenter:
    :return:
    """
    n = len(regs)
    res = [None] * 2
    sumBack = [1e10] * 2
    for i in range(n):
        for j in range(n):
            if j == i or j < i:
                continue
            for m in range(n):
                if m == i or m == j or m < j:
                    continue
                for h in range(n):
                    if h == i or h == j or h == m or h < m:
                        continue
                    tmpRegs = [regs[i], regs[j], regs[m], regs[h]]
                    # 去检测；
                    sortConor = SortFourCornor(tmpRegs)
                    # 检测；
                    d1 = CalcDistance(sortConor[0], sortConor[1])
                    d2 = CalcDistance(sortConor[1], sortConor[2])
                    d3 = CalcDistance(sortConor[2], sortConor[3])
                    d4 = CalcDistance(sortConor[0], sortConor[3])
                    tmpSubY = sortConor[0][1] - sortConor[1][1]
                    tmpSubX = sortConor[0][0] - sortConor[3][0]
                    if d1 * d2 * d3 * d4 == 0:
                        continue
                    tmpSum = math.fabs(d1 - d3) + math.fabs(d2 - d4) + math.fabs(tmpSubX) + math.fabs(tmpSubY)
                    # print(tmpSum)
                    if tmpSum < sumBack[0]:
                        if sumBack[0] < sumBack[1]:
                            sumBack[1] = sumBack[0] # 先备份;
                            res[1] = res[0]

                        sumBack[0] = tmpSum
                        res[0] = sortConor
                    else:
                        if tmpSum < sumBack[1]:
                            sumBack[1] = tmpSum
                            res[1] = sortConor
    # print(sumBack)
    AllRegs = []
    for v in res:
        for t in v:
            AllRegs.append(t)
    return AllRegs

def CalcLightFrom22Patch(img):
    """
    计算22分块的亮度；
    :param img:
    :return:
    """
    bgr = np.array(cv2.mean(img))
    x, y, z = CVT.rgb2xyz((bgr[2], bgr[1], bgr[0]))
    l, a, b = CVT.xyz2lab((x, y, z))
    return l

def CalcDeadLeaveAb(img):
    """
    计算枯叶图的A，B；
    :param img:
    :return:
    """
    bgr = np.array(cv2.mean(img))
    x, y, z = CVT.rgb2xyz((bgr[2], bgr[1], bgr[0]))
    l, a, b = CVT.xyz2lab((x, y, z))
    return a, b

def AnalysisAllImgs():
    """
    对目录下的所有图像进行分析；
    :return:
    """
    nKeys = len(LightImgs.keys())       # 键值数对应了光源数；
    resultReg = [0] * 8                 # 最终得到8个reg；  对所有的图像进行分析；
    bLocate = False                     # 已定位成功；
    dlrect = None
    colorRect = None
    for k, v in LightImgs.items():
        # 算平均；
        nImg = len(v)               # 该目录下有这么多图像；
        avgLight22 = 0
        avgDeltaAB = 0
        avgDetailR = 0
        bLocate = False                 # 同一个目录下的；
        sucessFiles = []
        failedFiles = []
        for imgPath in v:           # 同目录下；   首先定位reg；
            # 去进行分析；
            tmpPath = imgDir + k + "/" + imgPath
            if not bLocate or not bSame:               # 同样的；
                print("正在定位%s..." % tmpPath)
                regs = AL.PreDeal(tmpPath)         # 分析得到所有的定位reg               # 定位所有的reg；
                print("%s定位完成..." % tmpPath)
                regCenter = []
                for rg in regs:
                    center = CalcRegCenter(rg)
                    regCenter.append(center)
                # 对所有的regs进行删选；
                if len(regCenter) >= regNum:
                    AllRegs = GetRoiCornor(regCenter)
                    # 可以去定位枯叶图和24色卡了；
                    # 可以去定位枯叶图和24色卡了；
                    deadLeaveRegs, colorChartRegs = LocateDeadLeaveAnd24ColorChart(AllRegs)
                    # 去分析指标；
                    dlrect = CropDeadLeave(deadLeaveRegs)
                    colorRect = Crop24ColorChart(colorChartRegs)
                    if dlrect[2] == 0 or dlrect[3] == 0 or colorRect[2] == 0 or colorRect[3] == 0:
                        print("%s:定位失败" % imgPath)
                        failedFiles.append(tmpPath)
                        continue
                    bLocate = True              # 定位成功；
                else:
                    failedFiles.append(tmpPath)
                    print("%s:定位的reg数不对_%d" % (imgPath, len(regs)))
                    # 把图像复制出来；
                    tmpCopyDir = os.getcwd() + "/failedImg"
                    if not os.path.exists(tmpCopyDir):
                        os.mkdir(tmpCopyDir)
                    shutil.copy(tmpPath, tmpCopyDir)
                    continue
            sucessFiles.append(tmpPath)             # 成功的图像；
            img = cv2.imread(tmpPath)
            dealLeaveImg = img[int(dlrect[0]):int(dlrect[0] + dlrect[2]), int(dlrect[1]):int(dlrect[1] + dlrect[3])]
            cv2.imwrite("test.jpg", dealLeaveImg)
            tmpGrayImg = cv2.cvtColor(dealLeaveImg, cv2.COLOR_BGR2GRAY)
            tmpSpatialImg = CalcSpatialImg(tmpGrayImg)
            mtf,stdMtf,f = CalcLinearSpatialAndMtf(tmpSpatialImg)
            dr_1 = CalcDetailReserve(mtf, f)
            dr_2 = CalcDetailReserve(stdMtf, f)
            dr = dr_1 / dr_2 * 100.0
            dr = startDr + 100.0/(endDr - startDr) * (dr - startDr)

            # 枯叶图指标计算；
            tmpA, tmpB = CalcDeadLeaveAb(dealLeaveImg)

            colorImg = img[int(colorRect[0]):int(colorRect[0] + colorRect[2]), int(colorRect[1]):int(colorRect[1] + colorRect[3])]
            # 24色卡指标计算；
            tmpLight = CalcLightFrom22Patch(colorImg)

            # print(tmpLight, tmpA - stdLab[1], tmpB - stdLab[2], tmpDetailReserve)
            avgLight22 = avgLight22 + tmpLight
            avgDeltaAB = avgDeltaAB + pow(1.0 * (tmpA - stdLab[1]) * (tmpA - stdLab[1]) + (tmpB - stdLab[2]) * (tmpB - stdLab[2]), 0.5)
            avgDetailR = avgDetailR + dr
            print("%s定位成功" % imgPath)
                # 显示；
                # cv2.namedWindow("test", 0)
                # for reg in colorChartRegs:
                #     cv2.circle(img, (int(reg[1]), int(reg[0])), 30, (0, 0, 255), 5)  # reg里面0对应列了；
                # cv2.rectangle(img, (int(colorRect[1]), int(colorRect[0])),
                #               (int(colorRect[1] + colorRect[3]), int(colorRect[0] + colorRect[2])), (0, 0, 255), 3)
                # cv2.rectangle(img, (int(dlrect[1]), int(dlrect[0])),
                #               (int(dlrect[1] + dlrect[3]), int(dlrect[0] + dlrect[2])), (0, 0, 255), 3)
                # cv2.resizeWindow("test", 800, 600)
                # cv2.imshow("test", colorImg)
                # cv2.waitKey(0)
        if len(sucessFiles) == 0:
            print("该目录%s没有定位成功的" % k)
            continue
        print("成功：%d, 失败: %d" %(len(sucessFiles), len(failedFiles)))
        avgLight22 = 1.0 * avgLight22/len(sucessFiles)
        avgDeltaAB = 1.0 * avgDeltaAB/len(sucessFiles)
        avgDetailR = 1.0 * avgDetailR/len(sucessFiles)
        print("%s解析完成..." % k)
        print("正在存储数据")
        # 填入值到Excel；
        tmpSplit = k.split("_")
        tmpKey = "%s_%s" %(tmpSplit[0], tmpSplit[2])
        tmpPos = GetPosition(tmpKey)
        strDelta = "%.3f" % avgDeltaAB
        print("deltaAB:%.3f, L: %.3f, DR: %.3f" %(avgDeltaAB, avgLight22, avgDetailR))
        if tmpPos[0]:
            InsertTxt2Excell(strDelta, ExcelPath, sheetForDeadAndDeltaAB, tmpPos[0][0], tmpPos[0][1])
        if tmpPos[1]:
            InsertImg2Excel("test.jpg", ExcelPath, sheetForDeadAndDeltaAB, tmpPos[1])
        if tmpPos[2]:
            InsertTxt2Excell("%.3f" % avgLight22, ExcelPath, sheetForLightAndDetail, tmpPos[2][0], tmpPos[2][1])
        if tmpPos[3]:
            InsertTxt2Excell("%.3f" % avgDetailR, ExcelPath, sheetForLightAndDetail, tmpPos[3][0], tmpPos[3][1])
        print("%s数据存储完成" % k)

if __name__ == "__main__":
    WalkAllLightsDir(imgDir)
    # print(LightImgs)
    AnalysisAllImgs()